package keer.httpinterface.proxy;

import keer.httpinterface.http.HttpParams;

/**
 * 抽象类JsonCodec提供了JSON编码和解码的功能
 * 它定义了如何将对象编码为JSON字符串，以及如何解码JSON字符串为指定类型的对象
 * @see HttpParams
 *
 * @author Keer
 * @since 1.0.0
 */
@SuppressWarnings("StaticInitializerReferencesSubClass")
public abstract class JsonCodec {

    /**
     * 将参数对象编码为JSON字符串
     *
     * @param params 待编码的参数对象
     * @return 编码后的JSON字符串，如果无法编码则返回null
     * @throws Exception 如果编码过程中发生错误
     */
    public static String encodeParams(HttpParams params) throws Exception {
        // 将参数转换为对象
        Object o = params.convertToObject();
        if (o == null) {
            // 如果转换结果为空，则直接返回null
            return null;
        }
        // 调用抽象方法encode0进行实际的编码工作
        return codec.encode0(o);
    }

    /**
     * 将任意对象编码为JSON字符串
     *
     * @param object 待编码的对象
     * @return 编码后的JSON字符串
     * @throws Exception 如果编码过程中发生错误
     */
    public static String encode(Object object) throws Exception {
        // 直接调用抽象方法encode0进行编码
        return codec.encode0(object);
    }

    /**
     * 解码JSON字符串为指定类型的对象
     *
     * @param json JSON字符串
     * @param clazz 目标对象类型
     * @param <T> 指定类型的泛型参数
     * @return 解码后的对象
     * @throws Exception 如果解码过程中发生错误
     */
    public static <T> T decode(String json, Class<T> clazz) throws Exception {
        // 调用抽象方法decode0进行实际的解码工作
        return codec.decode0(json, clazz);
    }

    /**
     * 抽象方法，用于将对象编码为JSON字符串
     *
     * @param object 待编码的对象
     * @return 编码后的JSON字符串
     * @throws Exception 如果编码过程中发生错误
     */
    protected abstract String encode0(Object object) throws Exception;

    /**
     * 抽象方法，用于解码JSON字符串为指定类型的对象
     *
     * @param json JSON字符串
     * @param clazz 目标对象类型
     * @param <T> 指定类型的泛型参数
     * @return 解码后的对象
     * @throws Exception 如果解码过程中发生错误
     */
    protected abstract <T> T decode0(String json, Class<T> clazz) throws Exception;

    // 静态成员codec，用于实际的JSON编码和解码工作
    private static JsonCodec codec;

    // 静态代码块，用于初始化codec
    static {
        try {
            // 尝试加载Jackson库的ObjectMapper类
            Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
            // 如果成功加载，则使用Jackson实现类初始化codec
            codec = new JacksonJsonCodec();
        } catch (ClassNotFoundException ignored) {
            // 如果类找不到，则不做任何操作，codec保持为null
        }
    }

    /**
     * 构造方法，用于创建JsonCodec的子类实例
     * 由于JsonCodec是抽象类，所以外部不能直接实例化，只能实例化其子类
     */
    protected JsonCodec() {

    }
}
